package com.thornbird.vehiclerecycling.service.impl;

import com.thornbird.vehiclerecycling.entity.User;
import com.thornbird.vehiclerecycling.model.record.UserRecord;
import com.thornbird.vehiclerecycling.repository.UserRepository;
import com.thornbird.vehiclerecycling.service.OAuth2Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Configuration
@Transactional(rollbackFor = Exception.class)
public class OAuth2ServiceImpl implements OAuth2Service {

    @Value("${app.super-users}")
    private String superUsers;

    private final UserRepository userRepository;

    @Autowired
    public OAuth2ServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserRecord saveUser(Authentication authentication) {
        UserRecord userRecord = null;
        if (authentication != null && authentication instanceof OAuth2AuthenticationToken) {
            OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
            userRecord = parseUserRecord(token.getAuthorizedClientRegistrationId(), token.getPrincipal().getAttributes());
        }
        if (userRecord != null) {
            User user = userRepository.findFirstBySourceAndUserId(userRecord.getSource(), userRecord.getUserId());
            if (user == null) {
                user = new User();
                user.setSuperUser(isSuperUser(userRecord));
                user.setActive(user.getSuperUser());
            }
            userRecord.copyToEntity(user, "id", "createdAt", "updatedAt", "superUser", "active",
                    "realName", "companyName", "remark");
            userRepository.save(user);
            userRecord.parseEntity(user);
        }
        return userRecord;
    }

    private UserRecord parseUserRecord(String authorizedClientRegistrationId, Map<String, Object> userAttributes) {
        UserRecord userRecord = null;
        if (authorizedClientRegistrationId.equals("gitee")) {
            userRecord = new UserRecord();
            userRecord.setSource(authorizedClientRegistrationId);
            userRecord.setUserId(getAttributeValue(userAttributes, "id"));
            userRecord.setUserName(getAttributeValue(userAttributes, "name"));
            userRecord.setLoginName(getAttributeValue(userAttributes, "login"));
            userRecord.setEmail(getAttributeValue(userAttributes, "email"));
            userRecord.setAvatarUrl(getAttributeValue(userAttributes, "avatar_url"));
            userRecord.setProfileUrl(getAttributeValue(userAttributes, "html_url"));
            userRecord.setBio(getAttributeValue(userAttributes, "bio"));
            userRecord.setLastLoginTime(new Date());
        }
        return userRecord;
    }

    private boolean isSuperUser(UserRecord userRecord) {
        Set<String> superUserSet = new HashSet<>();
        String text = superUsers == null ? null : superUsers.trim();
        if (superUsers != null) {
            Collections.addAll(superUserSet, text.split(","));
        }
        return superUserSet.contains(userRecord.getFullName());
    }

    private String getAttributeValue(Map<String, Object> userAttributes, String key) {
        String value = null;
        if (userAttributes.containsKey(key) && userAttributes.get(key) != null) {
            value = String.valueOf(userAttributes.get(key));
        }
        return value;
    }

}
